package jblip;

/**
 * Operation failure message.
 * 
 * <p>
 * This class should be used as a container for system/client failure notices,
 * either for debugging purposes or for end-user information. Each of the
 * messages in this class contains an error number allowing simple comparison
 * and maintenance.
 * </p>
 * 
 * <p>
 * Currently the codes listed below are used:
 * <ul>
 * <li><strong>0</strong> -- operation unsupported,</li>
 * <li><strong>1</strong> -- exception occurred,</li>
 * <li>between <strong>100</strong> and <strong>999</strong> --
 * erroneous Blip HTTP server reply (the error code matches the response code),</li>
 * <li><strong>1000</strong> -- custom error messages.</li>
 * </p>
 * 
 * @author Krzysztof Sroka
 * @since 0.1
 */
public class ErrorMessage {

  private final static ErrorMessage HTTP_400;

  private final static ErrorMessage HTTP_401;

  private final static ErrorMessage HTTP_403;

  private final static ErrorMessage HTTP_404;

  private final static ErrorMessage HTTP_422;

  private final static ErrorMessage HTTP_500;

  private final static ErrorMessage HTTP_503;

  private final static ErrorMessage OPERATION_UNSUPPORTED;

  static {
    HTTP_400 = new ErrorMessage("HTTP request failed: [400] Bad request", 400);
    HTTP_401 = new ErrorMessage("HTTP request failed: [401] Unauthorized", 401);
    HTTP_403 = new ErrorMessage("HTTP request failed: [403] Forbidden", 403);
    HTTP_404 = new ErrorMessage("HTTP request failed: [404] Not Found", 404);
    HTTP_422 = new ErrorMessage(
        "HTTP request failed: [422] Unprocessable Entity", 422);
    HTTP_500 = new ErrorMessage(
        "HTTP request failed: [500] Internal Server Error", 500);
    HTTP_503 = new ErrorMessage(
        "HTTP request failed: [503] Server Unavailable", 503);
    OPERATION_UNSUPPORTED = new ErrorMessage(
        "Cliend doesn't support this operation", 0);
  }

  /**
   * Returns error message based on HTTP response code.
   * 
   * @param code
   *          HTTP response code.
   * @return Error message for the given HTTP code, with error code equal to the
   *         code of HTTP response.
   */
  public static ErrorMessage getHTTPErrorMessage(int code) {
    switch (code) {
    case 400:
      return HTTP_400;
    case 401:
      return HTTP_401;
    case 403:
      return HTTP_403;
    case 404:
      return HTTP_404;
    case 422:
      return HTTP_422;
    case 500:
      return HTTP_500;
    case 503:
      return HTTP_503;
    default:
      return new ErrorMessage("HTTP request failed: [" + code + "]", code);
    }
  }

  /**
   * Returns error message based on an exception.
   * 
   * @param e
   *          Exception caught during client's action.
   * @return Error message with the given exception's message and code number
   *         equal to 1.
   */

  public static ErrorMessage getExceptionMessage(Exception e) {
    StackTraceElement trace_elem = e.getStackTrace()[0];
    return new ErrorMessage("Exception caught: " + e.getMessage() + " at "
        + trace_elem.getClassName() + ":" + trace_elem.getLineNumber(), 1);
  }

  /**
   * Returns custom message, based on given message string.
   * 
   * @param message
   *          Message to be included in error notice.
   * @return New error message with contents equal to the given
   *         <code>message</code> parameter.
   */
  public static ErrorMessage getCustomMessage(String message) {
    return new ErrorMessage(message, 1000);
  }

  /**
   * Returns message for unsupported {@link BlipClient} operation.
   * 
   * @return Error message for client's unsupported operation, with code number
   *         0.
   */
  public static ErrorMessage getUnsupportedOperationMessage() {
    return OPERATION_UNSUPPORTED;
  }

  private final String message;

  private final Integer code;

  /**
   * Creates new error message instance.
   * 
   * @param msg
   *          Error message held by this instance.
   * @param code
   *          Integer code for this message.
   */
  protected ErrorMessage(String msg, Integer code) {
    message = msg;
    this.code = code;
  }

  /**
   * Gets textual representation of error message.
   * 
   * @return Textual representation of this error message.
   */
  @Override
  public String toString() {
    return message;
  }

  /**
   * Gets code number for this error message.
   * 
   * @return integer code of this message.
   */
  public Integer getCode() {
    return code;
  }
}
